class Singleton {
    // 饿汉模式
    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

class SingletonLazy {
    // 懒汉模式
    // 要加 volatile 防止指令重排序
    private static volatile SingletonLazy instance = null;

    private SingletonLazy() {
    }

    private static Object locker = new Object();

    public static SingletonLazy getInstance() {
        // 是否要加锁
        if (instance == null) {
            // 加锁防止出现线程安全问题
            synchronized (locker) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
}

public class ThreadDemo31 {


    private String[] queue;

    private int size; // 记录数组元素个数
    private int head; // 队首元素
    private int tali; // 队尾元素

    public ThreadDemo31(int capacity) {
        this.queue = new String[capacity];
    }

    Object locker = new Object();

    synchronized public void put(String elem) throws InterruptedException {
        // 插入前要判定数组是否已满
        while (size >= queue.length) {
            // 阻塞等待
            locker.wait();
        }

        // 插入元素
        queue[tali++] = elem;

        // tail走到末尾，回到开头
        if (tali >= queue.length) {
            tali = 0;
        }

        size++;
        locker.notify();
    }

    synchronized public String take() throws InterruptedException {
        while (size == 0) {
            // 阻塞等待
            locker.wait();
        }

        // 取走元素
        String old = queue[head];
        head++;

        if (head >= queue.length) {
            head = 0;
        }

        size--;
        locker.notify();
        return old;
    }

}
